package cn.kimming.rpc.remoting.registry;

import cn.kimming.rpc.common.exception.RpcException;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 服务端的zk连接
 * ClientRpcRegistry维护的是客户端的zk连接, 一个应用中不同的服务调用客户端可以配置不同的zkUrl, 持有多个zk连接
 * 而服务端只维持一个zk连接
 */
public class ServerRpcRegistry {
    private static CuratorFramework client;
    private static ServiceDiscovery<InstanceDetail> discovery;
    private static ExecutorService registryThreadPool = Executors.newCachedThreadPool();


    public static ExecutorService getRegistryThreadPool() {
        return registryThreadPool;
    }

    /**
     * 初始化client和discovery并返回
     * @return
     */
    public synchronized static void init(String registryUrl) {
        if (client != null && discovery != null) return;
        try {
            client = CuratorFrameworkFactory.newClient(registryUrl,
                    new ExponentialBackoffRetry(RegistryConstants.DEFAULT_BASE_SLEEP_TIME_MS,
                            RegistryConstants.DEFAULT_MAX_RETRIES));
            client.start();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RpcException("创建zk连接: " + registryUrl + " 失败");
        }

        try {
            discovery = ServiceDiscoveryBuilder.builder(InstanceDetail.class)
                    .basePath(RegistryConstants.BASE_PATH)
                    .client(client)
                    .build();
            discovery.start();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RpcException("初始化ServiceDiscovery: " + registryUrl + " 失败");
        }
    }

    public static ServiceDiscovery<InstanceDetail> getDiscovery() {
        return discovery;
    }

    public static CuratorFramework getClient() {
        return client;
    }

}
